Fs        = require "fs"
Url       = require "url"
Path      = require "path"
Fernet    = require "fernet"
Version   = require(Path.join(__dirname, "..", "..", "version")).Version
Octonode  = require "octonode"
JenkinsApi = require(Path.join(__dirname, "..", "api")).Api
extend    = require "node.extend"
ScopedClient = require "scoped-http-client"

AppsFile = process.env['HUBOT_DEPLOY_APPS_JSON'] or "apps.json"
AppsDirPath = process.env['HUBOT_DEPLOY_APPS_DIR_PATH'] or Path.resolve("./apps")
###########################################################################
readAppsConfig = () ->
  appsConfig = {}
  try
    if Fs.existsSync(AppsFile) && Fs.statSync(AppsFile).isFile()
      appsConfig = JSON.parse(Fs.readFileSync(AppsFile).toString())

    if Fs.existsSync(AppsDirPath) && Fs.statSync(AppsDirPath).isDirectory()
      for appsJSONFile in Fs.readdirSync(AppsDirPath).sort()
        if Fs.statSync(Path.join(AppsDirPath, appsJSONFile)).isFile()
          config = JSON.parse Fs.readFileSync(Path.join(AppsDirPath, appsJSONFile)).toString()
          appsConfig = extend appsConfig,config
  catch err
    throw new Error("Unable to parse your apps.json file in hubot-deploy #{err}")

  appsConfig

applications = readAppsConfig()
###########################################################################
class Deployment

  constructor: (@name, @ref, @task, @env, @force, @hosts) ->
    @room             = 'unknown'
    @user             = 'unknown'
    @adapter          = 'unknown'
    @userName         = 'unknown'
    @robotName        = 'hubot'
    @autoMerge        = true
    @environments     = [ "production" ]
    @requiredContexts = null

    @messageId        = undefined
    @threadId         = undefined
    @userToken        = ''

    @application = applications[@name]

    if @application?
      @job = @application['repository']

      @configureAutoMerge()
      @configureRequiredContexts()
      @configureEnvironments()

      @allowedRooms = @application['allowed_rooms']

    # set userToken from env
    @userToken = process.env.HUBOT_JENKINS_TOKEN

  isValidApp: ->
    @application?

  isValidEnv: ->
    @env in @environments

  isAllowedRoom: (room) ->
    !@allowedRooms? || room in @allowedRooms

  apiConfig: ->
    new JenkinsApi(@userToken, @application)

  deploy: (callback) ->
    name       = @name
    repository = @repository
    env        = @env
    ref        = @ref
    task       = @task
    hosts      = @hosts
    message = "#{@apiConfig().hostname}" + "/job/#{@application['job']}/build" + "||#{@userToken}"
    console.log message

    ScopedClient.create("http://#{@apiConfig().hostname}/job/#{@application['job']}/buildWithParameters?branch=#{@ref}").
      header("User-Agent", "hubot-deploy-v#{Version}").
      header("Authorization", "Basic #{@userToken}").
      post() (err, res, body) ->
        data = body
        if err
          data = err
        success = res.statusCode == 201
        message = ""
        if success and not message
          message = "#{task}ing #{name}/#{ref} to #{env}"
          if hosts
            message = "#{message}/#{hosts}"
        else
          message = data

        callback(err, res.statusCode, body, [], message)


  latest: (callback) ->
    job        = @application['job']
    name       = @name
    repository = @repository
    env        = @env
    ref        = @ref
    task       = @task
    hosts      = @hosts
    userToken  = @userToken
    application = @application
    message = "#{@apiConfig().hostname}" + "/job/#{@application['job']}/build" + "||#{@userToken}"
    console.log message

    #client = @apiConfig().client()
    @apiConfig().client().
      path("/job/#{@job}/api/json?pretty=true&tree=builds%5bdisplayName,duration,number,result,url,timestamp%5d").
      post() (err, res, body) ->
        bodyJson = JSON.parse body
        callback(err, bodyJson.builds, application)

  rawPost: (callback) ->
    path       = @apiConfig().path("repos/#{@repository}/deployments")
    repository = @repository
    env        = @env
    ref        = @ref

    @api().post path, @requestBody(), (err, status, body, headers) ->
      callback(err, status, body, headers)

  # Private Methods
  configureEnvironments: ->
    if @application['environments']?
      @environments = @application['environments']

    @env = 'staging' if @env == 'stg'
    @env = 'production' if @env == 'prod'

  configureAutoMerge: ->
    if @application['auto_merge']?
      @autoMerge = @application['auto_merge']
    if @force
      @autoMerge = false

  configureRequiredContexts: ->
    if @application['required_contexts']?
      @requiredContexts = @application['required_contexts']
    if @force
      @requiredContexts = [ ]

exports.Deployment = Deployment
